/*!
\copyright  Copyright (c) 2025 Qualcomm Technologies International, Ltd.
            All Rights Reserved.
            Qualcomm Technologies International, Ltd. Confidential and Proprietary.
\file
\ingroup    user_eq
\brief      Kymera implementation of UserEQ audio config

*/

#include "user_eq_audio_config.h"
#include "user_eq_ctx.h"
#include "user_eq_params_conversion.h"

#include <ps.h>
#include <logging.h>

#define FIRST_PRESET_PSKEY 9348
#define NUM_OF_PRESETS 12
#define LAST_PRESET_PSKEY (FIRST_PRESET_PSKEY + NUM_OF_PRESETS * 2)
#define USER_EQ_PSKEY 9470
#define NUM_OF_BANDS_OFFSET 7

uint8 UserEq_AudioConfigPopulatePresets(uint8 *presets)
{
    uint8 preset_index = 0;
    uint8 ucid = 1;
    uint32 key;

    for(key = FIRST_PRESET_PSKEY; key < LAST_PRESET_PSKEY; key += 2)
    {
        uint16 key_len = 0;
        PsReadAudioKey(key, NULL, 0, 0, &key_len);
        if(key_len)
        {
            if(presets)
            {
                presets[preset_index] = ucid;
            }
            ++preset_index;
        }
        ++ucid;
    }

    return preset_index;
}

static uint32 userEq_GetUint32FromPskey(uint32 key, uint16 offset)
{
    uint16 audio_key_buffer[2] = {0};
    uint16 new_key_len = 0;
    uint16 result;
    uint32 value = 0;

    result = PsReadAudioKey(key, audio_key_buffer, 2, offset, &new_key_len);

    value = audio_key_buffer[0] << 16 | audio_key_buffer[1];
    DEBUG_LOG_V_VERBOSE("userEq_GetUint32FromPskey key %d, offset %d, new_key_len %d, result %d, value 0x%x", key, offset, new_key_len, result, value);

    return value;
}

static void userEq_GetEqParamsFromPsKey(uint32 key, uint8 band, user_eq_parameter_set_t *param_set)
{
    uint32 type_in_q_format = userEq_GetUint32FromPskey(key, 11 + band * 8);
    uint32 freq_in_q_format = userEq_GetUint32FromPskey(key, 13 + band * 8);
    uint32 gain_in_q_format = userEq_GetUint32FromPskey(key, 15 + band * 8);
    uint32 q_in_q_format = userEq_GetUint32FromPskey(key, 17 + band * 8);

    if(param_set)
    {
        param_set->filter_type = type_in_q_format;
        param_set->cut_off_freq = UserEq_ParamsConversionCutOffFrequencyFromQFormat(freq_in_q_format);
        param_set->gain = UserEq_ParamsConversionGainFromQFormat(gain_in_q_format);
        param_set->q = UserEq_ParamsConversionQFromQFormat(q_in_q_format);

        DEBUG_LOG_ALWAYS("userEq_GetEqParamsFromPsKey stage type %d", param_set->filter_type);
        DEBUG_LOG_ALWAYS("userEq_GetEqParamsFromPsKey freq %d", param_set->cut_off_freq);
        DEBUG_LOG_ALWAYS("userEq_GetEqParamsFromPsKey gain %d %d", param_set->gain, param_set->gain/60);
        DEBUG_LOG_ALWAYS("userEq_GetEqParamsFromPsKey q %d", param_set->q);
    }
}

void UserEq_AudioConfigLoadEqParams(user_eq_data_t *eq_params)
{
    uint8 i;

    eq_params->number_of_presets = UserEq_AudioConfigPopulatePresets(NULL);

    eq_params->user.number_of_bands = userEq_GetUint32FromPskey(USER_EQ_PSKEY, NUM_OF_BANDS_OFFSET);
    eq_params->user.params = PanicUnlessMalloc(sizeof(user_eq_parameter_set_t) * eq_params->user.number_of_bands);

    for(i = 0; i < eq_params->user.number_of_bands; ++i)
    {
        userEq_GetEqParamsFromPsKey(USER_EQ_PSKEY, i, &eq_params->user.params[i]);
    }
}
